Secret
是 Kubernetes 中的一種資源,用於存儲和管理敏感數據,如密碼、OAuth tokens、SSH keys 等。Secret 允許你將這些敏感信息安全地傳遞給應用程式,而不需要將它們硬編碼到容器映像或組態檔案中。
將敏感信息存儲在 Secret 中而非硬編碼到應用程式中,可以帶來以下幾個好處:
用途:
ConfigMap
用於存儲非機密的配置數據(如環境變數、應用程式設定)。Secret
用於存儲機密數據(如密碼、憑證、tokens)。安全性:
ConfigMap
中的數據以明文形式存儲,對安全性要求不高。Secret
中的數據以 base64 編碼形式存儲,並且可以使用 Kubernetes 內建的加密機制來保護數據的安全性。使用場景:
ConfigMap
適用於一般的配置管理。Secret
適用於需要保密的數據管理。Opaque
:默認類型,用於存儲任意鍵值對。kubernetes.io/dockerconfigjson
:用於存儲 Docker 的鏡像拉取密鑰(dockerconfig.json
文件)。kubernetes.io/service-account-token
:存儲 Kubernetes ServiceAccount 的 token,通常由系統自動創建。kubernetes.io/tls
:用於存儲 TLS/SSL 憑證,包括 .crt
和 .key
文件。以下是一個使用 Secret 的 Kubernetes 組態檔範例:
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
username: dXNlcm5hbWU= # "username" base64 編碼後的值
password: cGFzc3dvcmQ= # "password" base64 編碼後的值
type
:Opaque
是鍵值類型,用於存儲任意類型的機密數據。data
:包含了 base64 編碼後的敏感數據。
username
和 password
是存儲在 Secret 中的兩個鍵值對,分別代表 base64 編碼後的使用者名稱和密碼。解碼後,username
的原始值是 "username"
,password
的原始值是 "password"
。
這個 Secret 可以用於應用程式中,通過環境變數或掛載到檔案的方式來安全地傳遞這些敏感數據。
這是實作要儲存的內容:
username=vincent
password=vincent_12345678
$ echo -n vincent_12345678 | base64 -w 0
說明:
-w 0
是為了避免額外的分段符號被選中加密
組態檔案: secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
stringData:
username: vincent
data:
password: dmluY2VudF8xMjM0NTY3OA==
kubectl apply -f secret.yaml
或者也可以使用 kubectl create
指令建立 secret。好處是可以直接輸入明碼,不用事先加密值
kubectl create
建立 secretkubectl create secret generic mysql-secret --from-literal='username=vincent' --from-literal='password=vincent_12345678'
儘管我們在 manifest 使用了 stringData 明碼輸入值,但使用 kubectl get
取得 mysql-secret 後,只剩下 data 欄位
kubectl get secrets mysql-secret -o yaml
結果如下
apiVersion: v1
items:
- apiVersion: v1
data:
password: dmluY2VudF8xMjM0NTY3OA==
username: dmluY2VudA==
kind: Secret
metadata:
[...]
name: mysql-secret
namespace: default
resourceVersion: "163920"
uid: c2d86028-dd87-4fc1-9cfb-e0cc7080e35b
type: Opaque
kind: List
metadata:
resourceVersion: ""
jsonpath
輸出 data 資訊,得到 base64 加密後的內容kubectl get secrets mysql-secret -o jsonpath='{.data}'
---
{"password":"dmluY2VudF8xMjM0NTY3OA==","username":"dmluY2VudA=="}
kubectl get secrets mysql-secret -o jsonpath='{.data.username}' | base64 -d
---
vincent
kubectl get secrets mysql-secret -o jsonpath='{.data.password}' | base64 -d
---
vincent_12345678
將 secrets 取得的值透過 base64 解碼後,與原始的資料相符
在 Pod 使用 Secret 資料的方法跟 ConfigMap 類似: 掛載為文件
、設為環境變量
。
組態檔案: pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "sleep 3600" ]
volumeMounts:
- name: vol
mountPath: "/mnt/data"
readOnly: true
volumes:
- name: vol
secret:
secretName: mysql-secret
kubectl apply -f pod.yaml
kubectl exec test-pod -- sh -c 'ls /mnt/data'
---
password
username
kubectl exec test-pod -- sh -c 'cat /mnt/data/password'
---
vincent_12345678
kubectl delete -f pod.yaml --now
組態檔案: pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "sleep 3600" ]
volumeMounts:
- name: vol
mountPath: "/mnt/data"
readOnly: true
volumes:
- name: vol
secret:
secretName: mysql-secret
items:
- key: username
path: my-group/my-username
kubectl apply -f pod.yaml
kubectl exec test-pod -- sh -c 'cat /mnt/data/my-group/my-username'
---
vincent
kubectl delete -f pod.yaml --now
組態檔案: pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "sleep 3600" ]
envFrom:
- secretRef:
name: mysql-secret
kubectl apply -f pod.yaml
kubectl exec -i -t test-pod -- sh -c 'echo $username $password'
---
vincent vincent_12345678
kubectl delete -f pod.yaml --now
組態檔案: pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "sleep 3600" ]
env:
- name: MYSQL_USERNAME
valueFrom:
secretKeyRef:
name: mysql-secret
key: username
kubectl apply -f pod.yaml
kubectl exec -i -t test-pod -- sh -c 'echo $MYSQL_USERNAME'
---
vincent
kubectl delete -f pod.yaml --now
Secret
提供了一種安全、集中化的方式來管理 Kubernetes 中的敏感資料,確保在應用程式部署過程中的資料安全性。與專注於一般配置管理的 ConfigMap
不同,Secret
著重於機密資訊的保護。
從功能和用途上看,Kubernetes 的 Secret
類似於 AWS 的 Secrets Manager,而 ConfigMap
則類似於 AWS Systems Manager Parameter Store。對這方面有興趣的朋友,可以從 AWS 相關服務的介紹開始深入了解。